Packages
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(terra)
## Warning: package 'terra' was built under R version 4.4.1
## terra 1.8.10
##
## Attaching package: 'terra'
##
## The following object is masked from 'package:tidyr':
##
## extract
library(sf)
## Warning: package 'sf' was built under R version 4.4.1
## Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
library(leaflet) #new
library(leaflet.extras) #new
## Warning: package 'leaflet.extras' was built under R version 4.4.1
Leaflet is….
…a Javascript library with an API we can access in R.
Wait, that’s a LOT of jargon. Can we add some clarity?
A simple setup
m <- leaflet()
m
What do you get?
Let’s try again
m <- leaflet() %>%
addTiles()
m
And now? What do you see?
Let’s build on that
m <- leaflet() %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addMarkers(lng = -81.350903, lat = 41.150377, popup="Our McGilvrey Hall GIS Lab")
m
What about now?
Create some data to plot. Let’s break this down a bit. What am I trying to do?
# First let's define a color palette we can sample from - this is only really necessary for the demo
mypal <- RColorBrewer::brewer.pal(12, "Set3")
# start with a data frame
df <- data.frame(
lat = rnorm(100) * 2 + 41,
lng = rnorm(100) * 2 - 81.5,
size = runif(100, 5, 20),
color = sample(mypal, 100, replace = T)
)
# then add the data frame to a leaflet map
m2 <- leaflet(df) %>% addTiles()
m2
What do you get? Why?
How can we interrogate the properties/attributes of an object?
The $ operator
m2$x
## $options
## $options$crs
## $crsClass
## [1] "L.CRS.EPSG3857"
##
## $code
## NULL
##
## $proj4def
## NULL
##
## $projectedBounds
## NULL
##
## $options
## named list()
##
## attr(,"class")
## [1] "leaflet_crs"
##
##
## $calls
## $calls[[1]]
## $calls[[1]]$method
## [1] "addTiles"
##
## $calls[[1]]$args
## $calls[[1]]$args[[1]]
## [1] "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
##
## $calls[[1]]$args[[2]]
## NULL
##
## $calls[[1]]$args[[3]]
## NULL
##
## $calls[[1]]$args[[4]]
## $calls[[1]]$args[[4]]$minZoom
## [1] 0
##
## $calls[[1]]$args[[4]]$maxZoom
## [1] 18
##
## $calls[[1]]$args[[4]]$tileSize
## [1] 256
##
## $calls[[1]]$args[[4]]$subdomains
## [1] "abc"
##
## $calls[[1]]$args[[4]]$errorTileUrl
## [1] ""
##
## $calls[[1]]$args[[4]]$tms
## [1] FALSE
##
## $calls[[1]]$args[[4]]$noWrap
## [1] FALSE
##
## $calls[[1]]$args[[4]]$zoomOffset
## [1] 0
##
## $calls[[1]]$args[[4]]$zoomReverse
## [1] FALSE
##
## $calls[[1]]$args[[4]]$opacity
## [1] 1
##
## $calls[[1]]$args[[4]]$zIndex
## [1] 1
##
## $calls[[1]]$args[[4]]$detectRetina
## [1] FALSE
##
## $calls[[1]]$args[[4]]$attribution
## [1] "© <a href=\"https://openstreetmap.org/copyright/\">OpenStreetMap</a>, <a href=\"https://opendatacommons.org/licenses/odbl/\">ODbL</a>"
##
##
##
##
##
## attr(,"leafletData")
## lat lng size color
## 1 40.99557 -79.13563 5.589956 #FFFFB3
## 2 41.51841 -82.07183 13.634710 #8DD3C7
## 3 39.58837 -79.98233 12.287202 #8DD3C7
## 4 36.02427 -79.34099 11.800571 #8DD3C7
## 5 41.61471 -79.69419 6.796672 #FB8072
## 6 41.07081 -84.58328 14.169870 #FFFFB3
## 7 39.20428 -83.48465 6.726310 #BC80BD
## 8 39.38648 -81.08120 16.762243 #FB8072
## 9 42.91117 -84.08719 18.635823 #FDB462
## 10 42.97757 -82.08426 10.449133 #FDB462
## 11 43.61776 -79.42000 15.345889 #80B1D3
## 12 39.62743 -83.58673 19.659007 #FFED6F
## 13 37.07969 -81.27965 6.377662 #FB8072
## 14 39.62185 -81.49565 7.631777 #BC80BD
## 15 45.03158 -79.01240 11.398857 #FDB462
## 16 41.96567 -83.54479 6.826523 #D9D9D9
## 17 40.00618 -84.12575 5.875669 #8DD3C7
## 18 43.49293 -83.94984 19.223998 #FFFFB3
## 19 42.27354 -83.33615 9.413458 #FFFFB3
## 20 40.70913 -81.94301 17.432854 #BEBADA
## 21 38.90938 -82.10358 5.930295 #FFFFB3
## 22 43.05722 -80.53805 9.756234 #D9D9D9
## 23 43.54577 -78.81916 11.091415 #BC80BD
## 24 41.19503 -80.64093 6.551020 #BEBADA
## 25 38.57878 -81.84099 15.786930 #FB8072
## 26 38.58378 -80.43737 15.786754 #BC80BD
## 27 39.72807 -77.50587 18.862740 #D9D9D9
## 28 42.77109 -80.81386 19.111744 #BC80BD
## 29 44.22270 -80.13685 6.637261 #FCCDE5
## 30 39.27048 -83.17801 10.424794 #FFFFB3
## 31 40.92306 -79.88249 10.578742 #FDB462
## 32 41.11225 -81.04566 8.981571 #FFFFB3
## 33 40.21275 -80.95464 15.209068 #FFED6F
## 34 41.54495 -81.69650 11.198912 #CCEBC5
## 35 37.26881 -78.70891 5.168262 #FFED6F
## 36 39.55594 -80.39995 9.460870 #FDB462
## 37 36.68614 -83.35930 10.466847 #BEBADA
## 38 42.06948 -80.32987 7.980701 #8DD3C7
## 39 41.83519 -84.58168 15.495430 #D9D9D9
## 40 41.74426 -79.89403 7.314745 #FFFFB3
## 41 43.63476 -81.66410 19.668826 #80B1D3
## 42 42.56280 -82.41770 7.623219 #B3DE69
## 43 39.68978 -84.96293 9.950413 #B3DE69
## 44 44.94753 -77.82024 11.327422 #FFFFB3
## 45 40.65368 -78.50057 10.269610 #CCEBC5
## 46 39.22979 -82.24579 19.261176 #BEBADA
## 47 44.07065 -81.63558 13.004268 #FB8072
## 48 40.36046 -84.64513 6.912204 #FDB462
## 49 40.80705 -79.64504 12.464519 #FCCDE5
## 50 42.56957 -79.79366 17.316795 #FFFFB3
## 51 43.03161 -80.02926 19.236746 #FFFFB3
## 52 41.43904 -80.75981 5.145617 #80B1D3
## 53 40.04199 -81.15778 13.480114 #FFFFB3
## 54 43.55065 -79.91475 5.485484 #D9D9D9
## 55 41.05792 -78.86068 10.242263 #80B1D3
## 56 38.86173 -81.66307 18.627972 #BC80BD
## 57 40.47928 -81.42816 10.962013 #BC80BD
## 58 39.66669 -81.55837 19.552184 #D9D9D9
## 59 42.00286 -78.83213 9.499974 #8DD3C7
## 60 38.42290 -83.60183 17.805416 #B3DE69
## 61 46.28538 -81.50380 8.364720 #FCCDE5
## 62 44.84312 -77.60632 10.032009 #FCCDE5
## 63 38.50044 -84.72521 12.245606 #FFFFB3
## 64 39.49851 -83.15436 16.234848 #CCEBC5
## 65 41.98286 -78.79072 5.012674 #BC80BD
## 66 36.81610 -84.71510 11.772750 #B3DE69
## 67 44.08290 -82.41083 6.536815 #B3DE69
## 68 42.04413 -80.28196 11.855492 #FFED6F
## 69 39.69804 -81.37702 5.267861 #FFFFB3
## 70 39.10524 -80.87203 12.511442 #8DD3C7
## 71 40.89387 -81.02553 9.459610 #FCCDE5
## 72 43.95761 -81.64442 9.045999 #FFFFB3
## 73 42.32377 -82.98972 6.734687 #B3DE69
## 74 43.99951 -82.99287 8.990918 #FFED6F
## 75 43.69136 -81.29568 18.295786 #8DD3C7
## 76 44.55294 -84.79464 18.206944 #BEBADA
## 77 39.69705 -83.94369 14.111976 #FDB462
## 78 40.71315 -81.55757 12.101988 #D9D9D9
## 79 42.00901 -86.38394 14.269304 #B3DE69
## 80 41.66195 -80.31610 7.334835 #D9D9D9
## 81 39.57646 -79.49651 5.376891 #FFED6F
## 82 38.07819 -85.77021 14.029262 #CCEBC5
## 83 42.09102 -81.57860 7.852826 #FDB462
## 84 40.56325 -81.34357 19.253815 #FFFFB3
## 85 39.21289 -79.80518 9.615235 #FDB462
## 86 44.20685 -81.95846 6.812211 #CCEBC5
## 87 40.95139 -85.58172 7.794516 #FFED6F
## 88 39.64487 -85.90070 15.946174 #8DD3C7
## 89 37.02554 -81.26042 7.025145 #FB8072
## 90 39.64444 -81.40372 16.115854 #8DD3C7
## 91 39.80332 -76.97088 7.306852 #D9D9D9
## 92 41.44260 -81.67425 11.255314 #FFED6F
## 93 40.53179 -83.21473 7.941580 #FFED6F
## 94 40.29679 -81.22706 18.578634 #FFFFB3
## 95 41.83633 -79.28368 11.910308 #FB8072
## 96 43.00870 -77.94653 9.014591 #FCCDE5
## 97 40.54698 -83.43580 8.368629 #CCEBC5
## 98 40.77970 -80.14204 10.636852 #FFED6F
## 99 39.20020 -82.22742 6.221372 #FCCDE5
## 100 41.84033 -79.26274 8.804855 #BEBADA
What do the data look like?
Let’s try again to visualize it. Again, break down the code first
# first one
m2 %>% addCircleMarkers(radius = ~size, color = ~color, fill = FALSE)
## Assuming "lng" and "lat" are longitude and latitude, respectively
# second one
m2 %>% addCircleMarkers(radius = runif(100, 4, 10), color = c('red'))
## Assuming "lng" and "lat" are longitude and latitude, respectively
What happened this time???
Let’s add some more tiles
# Let's check out some other tiles
m <- leaflet() %>% setView(lng = -81.34, lat = 41.145, zoom = 14)
m %>% addTiles()
# third party tiles using addProvider() function
m %>% addProviderTiles(providers$Stadia.StamenToner)
m %>% addProviderTiles(providers$CartoDB.Positron)
m %>% addProviderTiles(providers$CartoDB.DarkMatter)
m %>% addProviderTiles(providers$Esri.NatGeoWorldMap)
Give it a shot. What do you like?
parks <- sf::read_sf("../data/static_mapping/oh_parks.gpkg") %>%
sf::st_transform(., "EPSG:4326") # transform to WGS84 to make Leaflet happy
# set up the map, zoom out a bit
mp <- leaflet(data = parks) %>% setView(lng = -81.34, lat = 41.145, zoom = 10)
mp %>% addTiles() %>%
addPolygons(popup = ~NAME, label = ~NAME)
What’s the difference between popup and label?
Who wants to help break down this code?
portage_streams <- sf::read_sf("../data/static_mapping/tl_2022_39133_linearwater/tl_2022_39133_linearwater.shp") %>%
sf::st_transform(., "EPSG:4326") # transform to WGS84 to make Leaflet happy
leaflet(data = portage_streams) %>%
setView(lng = -81.34, lat = 41.145, zoom = 10) %>%
addTiles() %>%
addPolylines(., color = "blue",
popup = ~paste0(FULLNAME, ": ", LINEARID))
What happened?
(Note, there’s a difference here in calling various datasets)
m.both <- leaflet() %>%
setView(lng = -81.34, lat = 41.145, zoom = 10) %>%
addProviderTiles(providers$Esri.NatGeoWorldMap) %>%
addPolygons(data = parks, popup = ~NAME, label = ~NAME, color = "green") %>%
addPolylines(data = portage_streams, color = "blue",
popup = ~paste0(FULLNAME, ": ", LINEARID))
m.both
leaflet.extras package